package sao.dao;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Time;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import sao.bd.BD;
import sao.modelo.Agendamento;
import sao.modelo.Disponibilidade;
import sao.modelo.Perfil;
import sao.modelo.Usuario;
import sao.modelo.UsuarioMedico;

public class Dao {

	
	/**
	 * Cria um usuário caso o mesmo seja encontrado no banco de dados
	 * 
	 * @param login
	 *            - Login do usuário a ser testado
	 * @param senha
	 *            - Senha do usuário
	 * @return Um Usuario ou null em caso de não ser encontrado
	 * @throws SQLException
	 * @throws NumberFormatException
	 * @throws ClassNotFoundException
	 */
	public Usuario getUsuario(String login, String senha)
			throws NumberFormatException, SQLException, ClassNotFoundException {
		
		Usuario usuario = null;
		String sql = "SELECT * FROM Usuario WHERE login='" + login + "'";
		BD bd = new BD();
		ResultSet rs = bd.executarStatement(sql);
		while (rs.next()) {
			if (rs.getString("senha").equals(senha)) {
				int codigo = Integer.parseInt(rs.getString("cod_usuario"));
				String cpf = rs.getString("cpf");
				// campo login
				// campo senha
				String nome = rs.getString("nome");
				String endereco = rs.getString("endereco");
				String telefone = rs.getString("cpf");
				String email = rs.getString("email");
				String genero = rs.getString("genero");
				String tipoUsuario = rs.getString("tipo_usuario");
				Perfil perfil = new Perfil(tipoUsuario);
				// Cria o objeto usuário
				usuario = new Usuario(codigo, nome, login, genero, cpf,
						endereco, telefone, email, tipoUsuario, perfil);
			}
		}
		bd.fechar();
		// Retorna o usuário ou nulo se a autenticação falhou
		return usuario;
		
	}//FIM método getUsuario

	
	/**
	 * Retorna a Disponibilidade do Médico
	 * 
	 * @param medico
	 *            - Usuário médico
	 * @param diaDaSemana
	 *            - Dia da semana que se deseja saber a disponibilidade
	 * @return Um objeto Disponibilidade
	 * @throws SQLException
	 * @throws ClassNotFoundException
	 * @see Disponibilidade
	 */
	public Disponibilidade getDisponibilidade(UsuarioMedico medico,
			int diaDaSemana) throws ClassNotFoundException, SQLException {
		
		Disponibilidade disp = null;
		BD bd = new BD();
		String sql = "SELECT * FROM Disponibilidade WHERE cod_medico = "
				+ medico.getCodigo() + " AND dia_semana = " + diaDaSemana;
		ResultSet r = bd.executarStatement(sql);
		if (r.next()) {
			disp = new Disponibilidade(
					diaDaSemana, 
					r.getTime("inicio_horario1"),
					r.getTime("fim_horario1"), 
					r.getTime("inicio_horario2"), 
					r.getTime("fim_horario2")
					);
		}
		bd.fechar();
		return disp;
		
	}//FIM método getDisponibilidade

	
	/**
	 * Retorna um usuário do tipo médico, após consulta na base de dados
	 * 
	 * @param codigoMedico - Inteiro com o código do médico
	 * @return Um usuário do tipo médico
	 * @throws SQLException
	 * @throws ClassNotFoundException
	 */
	public UsuarioMedico getUsuarioMedico(int codigoMedico)
			throws SQLException, ClassNotFoundException {
		
		UsuarioMedico medico = null;
		String sql = "SELECT u.*, m.crm, m.especialidade FROM Usuario u "
				+ "INNER JOIN Medico m ON u.cod_usuario = m.cod_medico "
				+ "WHERE cod_usuario = " + codigoMedico;
		BD bd = new BD();
		ResultSet rs = bd.executarStatement(sql);
		while (rs.next()) {
			String cpf = rs.getString("cpf");
			String login = rs.getString("login");
			// campo senha
			String nome = rs.getString("nome");
			String endereco = rs.getString("endereco");
			String telefone = rs.getString("cpf");
			String email = rs.getString("email");
			String genero = rs.getString("genero");
			String tipoUsuario = rs.getString("tipo_usuario");
			Perfil perfil = new Perfil(tipoUsuario);
			String crm = rs.getString("crm");
			String especialidade = rs.getString("especialidade");
			// Cria o objeto usuário
			medico = new UsuarioMedico(codigoMedico, nome, login, genero, cpf,
					endereco, telefone, email, tipoUsuario, perfil, crm,
					especialidade);
		}
		// Retorna o usuário ou nulo se a autenticação falhou
		bd.fechar();
		return medico;
		
	}// FIM método getUsuarioMedico

	
	/**
	 * Consulta os agendamentos existentes para um determinado dia-mês-ano
	 * 
	 * @param medico - O objeto médico cujos agendamentos serão consultados
	 * @param ano - O ano a ser consultado
	 * @param mes - O mês a ser consultado
	 * @param dia - O dia a ser consultado
	 * @return Uma List de Date's representando os agendamentos
	 * @throws ClassNotFoundException
	 * @throws SQLException
	 */
	public List<Time> getAgendamentosDia(UsuarioMedico medico, int ano,
			int mes, int dia) throws ClassNotFoundException, SQLException {
		
		List<Time> agendamentos = new ArrayList<Time>();
		BD bd = new BD();
		// Constroi a consulta
		String sql = "SELECT horario FROM Agendamento WHERE cod_medico = "
				+ medico.getCodigo() + " AND horario BETWEEN '" + ano + "-"
				+ mes + "-" + dia + " 00:00:00' AND '" + ano + "-" + mes + "-"
				+ dia + " 23:59:59'";

		ResultSet r = bd.executarStatement(sql);
		Time umAgendamento;
		while (r.next()) {
			umAgendamento = r.getTime("horario");
			agendamentos.add(umAgendamento);
		}
		bd.fechar();
		return agendamentos;
		
	}//FIM método getAgendamentosDia

	
	/**
	 * Insere um novo agendamento no banco de dados
	 * 
	 * @param codPaciente - Inteiro representando o código do paciente
	 * @param codMedico - Inteiro representando o código do médico
	 * @param horario - String com o horário no formato 'dd-MM-yyy hh:mm:ss'
	 * @return Um inteiro com o número de linhas afetadas pela execução do
	 *         comando SQL
	 * @throws ClassNotFoundException
	 * @throws SQLException
	 */
	public int insertAgendamento(int codPaciente, int codMedico, String horario)
			throws ClassNotFoundException, SQLException {
		
		String sql = "INSERT INTO Agendamento(cod_paciente,cod_medico,horario) VALUES("
				+ codPaciente + ", " + codMedico + ", '" + horario + "')";
		BD bd = new BD();
		return bd.executarUpdate(sql);
		
	}//FIM método insertAgendamento
	

	/**
	 * Retorna os dados de um agendamento específico, onde são especificados os
	 * códigos do paciente médico e o horário de início da consulta. Usado
	 * principalmente para verificar se aquele horário já está ocupado
	 * 
	 * @param codMedico - O código do médico
	 * @param codPaciente - O código do paciente
	 * @param horario - String com o horário da consulta no formato 
	 * 			'dd-MM-yyy hh:mm:ss'
	 * @return Uma lista de agendamentos que foram encontrados. Caso nenhum seja
	 *         encontrado, retorna uma lista com zero itens
	 * @throws ClassNotFoundException
	 * @throws SQLException
	 */
	public List<Agendamento> getAgendamentoEspecifico(int codMedico,
			int codPaciente, String horario) throws ClassNotFoundException,
			SQLException {
		
		List<Agendamento> agendamentos = new ArrayList<Agendamento>();
		BD bd = new BD();
		// Constroi a consulta
		String sql = "SELECT * FROM Agendamento WHERE cod_paciente = "
				+ codPaciente + " AND cod_medico = " + codMedico
				+ " AND horario = '" + horario + "'";

		ResultSet r = bd.executarStatement(sql);
		while (r.next()) {
			agendamentos.add(
				new Agendamento(
					r.getInt("cod_agendamento"), 
					r.getInt("cod_paciente"), r.getInt("cod_medico"), 
					r.getDate("horario"))
				);
		}
		bd.fechar();
		return agendamentos;
		
	}//FIM método getAgendamentoEspecifico

	
	/**
	 * Retorna os agendamentos, dados os códigos do paciente e do médico
	 * 
	 * @param codMedico - O código do médico
	 * @param codPaciente - O código do paciente
	 * @return Uma lista de agendamentos que foram encontrados. Caso nenhum seja
	 *         encontrado, retorna uma lista com zero itens
	 * @throws ClassNotFoundException
	 * @throws SQLException
	 */
	public List<Agendamento> getAgendamentos(int codMedico, int codPaciente)
			throws ClassNotFoundException, SQLException {

		List<Agendamento> agendamentos = new ArrayList<Agendamento>();
		BD bd = new BD();
		// Constroi a consulta
		String sql = "SELECT * FROM Agendamento WHERE cod_paciente = "
				+ codPaciente + " AND cod_medico = " + codMedico;

		ResultSet r = bd.executarStatement(sql);
		while (r.next()) {
			agendamentos.add(
				new Agendamento(
					r.getInt("cod_agendamento"), 
					r.getInt("cod_paciente"), 
					r.getInt("cod_medico"), 
					r.getDate("horario"))
				);
		}
		bd.fechar();
		return agendamentos;
		
	}//FIM método getAgendamentos

	
	/**
	 * Retorna os agendamentos, dados os códigos do paciente e do médico
	 * 
	 * @param codMedico - O código do médico
	 * @return Uma lista de agendamentos que foram encontrados. Caso nenhum seja
	 *         encontrado, retorna uma lista com zero itens
	 * @throws ClassNotFoundException
	 * @throws SQLException
	 */
	public List<Agendamento> getAgendamentosPorMedico(int codMedico)
			throws ClassNotFoundException, SQLException {

		List<Agendamento> agendamentos = new ArrayList<Agendamento>();
		BD bd = new BD();
		// Constroi a consulta
		String sql = "SELECT * FROM Agendamento WHERE cod_medico = "
				+ codMedico;

		ResultSet r = bd.executarStatement(sql);
		while (r.next()) {
			agendamentos.add(
				new Agendamento(
					r.getInt("cod_agendamento"), 
					r.getInt("cod_paciente"),
					r.getInt("cod_medico"), 
					r.getDate("horario"))
				);
		}
		bd.fechar();
		return agendamentos;
		
	}//FIM método getAgendamentosPorMedico

	
	/**
	 * Retorna os agendamentos, dados os códigos do paciente e do médico
	 * 
	 * @param codPaciente - O código do paciente
	 * @return Uma lista de agendamentos que foram encontrados. Caso nenhum seja
	 *         encontrado, retorna uma lista com zero itens
	 * @throws ClassNotFoundException
	 * @throws SQLException
	 */
	public List<Agendamento> getAgendamentosPorPaciente(int codPaciente)
			throws ClassNotFoundException, SQLException {

		List<Agendamento> agendamentos = new ArrayList<Agendamento>();
		BD bd = new BD();
		// Constroi a consulta
		String sql = "SELECT * FROM Agendamento WHERE cod_paciente = "
				+ codPaciente;

		ResultSet r = bd.executarStatement(sql);
		while (r.next()) {
			agendamentos.add(
				new Agendamento(
					r.getInt("cod_agendamento"), 
					r.getInt("cod_paciente"),
					r.getInt("cod_medico"), 
					r.getDate("horario"))
				);
		}
		bd.fechar();
		return agendamentos;
		
	}//FIM método getAgendamentosPorPaciente
	

	/**
	 * Retorna os agendamentos ativos de um dado paciente. Os agendamentos
	 * ativos são aqueles cuja data seja igual ou superior à data de hoje
	 * 
	 * @param codPaciente - O código do médico
	 * @return Uma lista de agendamentos que foram encontrados. Caso nenhum seja
	 *         encontrado, retorna uma lista com zero itens
	 * @throws SQLException
	 * @throws ClassNotFoundException
	 * @throws ClassNotFoundException
	 * @throws SQLException
	 */
	public List<Agendamento> getAgendamentosAtivosPorPaciente(int codPaciente)
			throws ClassNotFoundException, SQLException {

		List<Agendamento> agendamentos = new ArrayList<Agendamento>();
		BD bd = new BD();
		Calendar cal = Calendar.getInstance();// Data de hoje
		DateFormat f = new SimpleDateFormat("yyyy-MM-dd");// Formatador da data
															// para o SQL

		// Constroi a consulta
		String sql = "SELECT * FROM Agendamento WHERE cod_paciente = "
				+ codPaciente + " AND horario > '" + f.format(cal.getTime())
				+ " 00:00:00' ORDER BY horario";

		ResultSet r = bd.executarStatement(sql);
		while (r.next()) {
			agendamentos.add(
				new Agendamento(
					r.getInt("cod_agendamento"), 
					r.getInt("cod_paciente"),
					r.getInt("cod_medico"), 
					r.getTimestamp("horario"))
				);
		}
		bd.fechar();
		return agendamentos;
		
	}//FIM método getAgendamentosAtivosPorPaciente
	

	/**
	 * Exclui um agendamento do banco de dados dado o seu código
	 * 
	 * @param codAgendamento - Inteiro representando o código do agendamento
	 * @return Um valor inteiro com o número de linhas afetadas pela consulta
	 * @throws ClassNotFoundException
	 * @throws SQLException
	 */
	public int excluirAgendamento(int codAgendamento)
			throws ClassNotFoundException, SQLException {

		String sql = "DELETE FROM Agendamento WHERE cod_agendamento = "
				+ codAgendamento;
		BD bd = new BD();
		return bd.executarUpdate(sql);
	}


	public List<Agendamento> getAgendamentosPorPeriodoPorPaciente(int codPaciente,
			String dataInicio) throws ClassNotFoundException, SQLException {
		
		List<Agendamento> agendamentos = new ArrayList<Agendamento>();
		BD bd = new BD();
		// Constroi a consulta
		String sql = "SELECT * FROM Agendamento WHERE cod_paciente = "
				+ codPaciente + " AND horario > '" + dataInicio + "' ORDER BY horario";

		ResultSet r = bd.executarStatement(sql);
		while (r.next()) {
			agendamentos.add(
				new Agendamento(
					r.getInt("cod_agendamento"), 
					r.getInt("cod_paciente"),
					r.getInt("cod_medico"), 
					r.getTimestamp("horario"))
				);
		}
		bd.fechar();
		return agendamentos;
		
	}
	

}// FIM classe Dao
